#include "wft0420.h"
#include "spi_port.h"

static const unsigned char epd_lut_vcom0[] = {
    0x00, 0x08, 0x08, 0x00, 0x00, 0x02,	
	0x00, 0x0F, 0x0F, 0x00, 0x00, 0x01,	
	0x00, 0x08, 0x08, 0x00, 0x00, 0x02,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00,
};
static const unsigned char epd_lut_ww[] = {
	0x50, 0x08, 0x08, 0x00, 0x00, 0x02,	
	0x90, 0x0F, 0x0F, 0x00, 0x00, 0x01,	
	0xA0, 0x08, 0x08, 0x00, 0x00, 0x02,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char epd_lut_bw[] = {
	0x50, 0x08, 0x08, 0x00, 0x00, 0x02,	
	0x90, 0x0F, 0x0F, 0x00, 0x00, 0x01,	
	0xA0, 0x08, 0x08, 0x00, 0x00, 0x02,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const unsigned char epd_lut_wb[] = {
	0xA0, 0x08, 0x08, 0x00, 0x00, 0x02,	
	0x90, 0x0F, 0x0F, 0x00, 0x00, 0x01,	
	0x50, 0x08, 0x08, 0x00, 0x00, 0x02,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
};
static const unsigned char epd_lut_bb[] = {
	0x20, 0x08, 0x08, 0x00, 0x00, 0x02,	
	0x90, 0x0F, 0x0F, 0x00, 0x00, 0x01,	
	0x10, 0x08, 0x08, 0x00, 0x00, 0x02,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	
};


static void epd_reset(void)
{
    EPD_W21_RST_1;
    epd_delay_ms(200);
    EPD_W21_RST_0;
    epd_delay_ms(2);
    EPD_W21_RST_1;
    epd_delay_ms(200);
}

static void epd_cmd_w(uint8_t Reg)
{
    EPD_W21_DC_0;
    EPD_W21_CS_0;
    spi_write(Reg);
    EPD_W21_CS_1;
}


static void epd_data_w(uint8_t Data)
{
    EPD_W21_DC_1;
    EPD_W21_CS_0;
    spi_write(Data);
    EPD_W21_CS_1;
}



static void epd_readbusy(void)
{
    unsigned char busy;
    do {
        epd_cmd_w(0x71);
        busy = !(isEPD_W21_BUSY & 0x01);
    } while (busy);
    epd_delay_ms(200);
}


static void epd_update(void)
{
    epd_cmd_w(0x12); // DISPLAY_REFRESH
    epd_delay_ms(100);
    epd_readbusy();
}

static void epd_set_lut(void)
{
    unsigned int count;
    epd_cmd_w(0x20);
    for (count = 0; count < 36; count++) {
        epd_data_w(epd_lut_vcom0[count]);
    }

    epd_cmd_w(0x21);
    for (count = 0; count < 36; count++) {
        epd_data_w(epd_lut_ww[count]);
    }

    epd_cmd_w(0x22);
    for (count = 0; count < 36; count++) {
        epd_data_w(epd_lut_bw[count]);
    }

    epd_cmd_w(0x23);
    for (count = 0; count < 36; count++) {
        epd_data_w(epd_lut_wb[count]);
    }

    epd_cmd_w(0x24);
    for (count = 0; count < 36; count++) {
        epd_data_w(epd_lut_bb[count]);
    }
}



int e4v2_wft0420_init(void)
{
    epd_reset();
    epd_cmd_w(0x01); // POWER SETTING
    epd_data_w(0x03);
    epd_data_w(0x00);
    epd_data_w(0x2b);
    epd_data_w(0x2b);

    epd_cmd_w(0x06); // boost soft start
    epd_data_w(0x17); // A
    epd_data_w(0x17); // B
    epd_data_w(0x17); // C

    epd_cmd_w(0x04);
    epd_readbusy();

    epd_cmd_w(0x00); // panel setting
    epd_data_w(0xbf); // KW-bf   KWR-2F	BWROTP 0f	BWOTP 1f

    epd_cmd_w(0x30);
    epd_data_w(0x3c); // 3A 100HZ   29 150Hz 39 200HZ	31 171HZ

    epd_cmd_w(0x61); // resolution setting
    epd_data_w(0x01);
    epd_data_w(0x90); // 400
    epd_data_w(0x01); // 300
    epd_data_w(0x2c);

    epd_cmd_w(0x82); // vcom_DC setting
    epd_data_w(0x12);

    epd_cmd_w(0X50);
    epd_data_w(0x97);

    epd_set_lut();
    return 0;
}



int e4v2_wft0420_clean(void)
{
    epd_cmd_w(0x10);
    for (uint16_t j = 0; j < 300; j++) {
        for (uint16_t i = 0; i < 50; i++) {
            epd_data_w(0xFF);
        }
    }

    epd_cmd_w(0x13);
    for (uint16_t j = 0; j < 300; j++) {
        for (uint16_t i = 0; i < 50; i++) {
            epd_data_w(0xFF);
        }
    }
    epd_cmd_w(0x12);
    epd_delay_ms(1);
    epd_update();
    return 0;
}

static uint8_t get_data(uint8_t * color, uint8_t pix_size)
{
    uint8_t data = 0;
    int i =0, j = 0;
    for (i = 0; i < 8; i++) {
        data = data | (color[j] << (7-i));
        j = j + pix_size;
    }
    return data;
}
int e4v2_wft0420_draw(uint8_t* wbuf, uint8_t pix_size, uint32_t hor_res, uint32_t ver_res)
{
    int i = 0, j = 0;
    uint8_t data;
    epd_cmd_w(0x13);
    for (i = 0; i < ver_res; i++) {
        for (j = 0; j < hor_res; ) {
            data = get_data(&wbuf[j + i * hor_res * pix_size], pix_size);
            epd_data_w(data);
            j = j + 8 * pix_size;
        }
    }
    epd_cmd_w(0x12);
    epd_delay_ms(10);
    epd_update();
    return 0;
}


int e4v2d_wft0420_sleep(void)
{
	epd_cmd_w(0x50); // DEEP_SLEEP
    epd_data_w(0XF7);

    epd_cmd_w(0x02); // POWER_OFF
    epd_readbusy();

    epd_cmd_w(0x07); // DEEP_SLEEP
    epd_data_w(0XA5);
    return 0;
}

int e4v2_wft0420_stop(void)
{
    epd_power_off();
    return 0;
}
